#include <stdio.h>
#include <unistd.h>

#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/user.h> // #include <sys/reg.h>

void get_ins_cnt(pid_t child)
{
    // use single step to get total instrctions
    int cnt = 0;
    int status;
    struct user_regs_struct regs;
    long long unsigned int ins;
    wait(&status);
    while (WIFSTOPPED(status)) {
        cnt++;
        ptrace(PTRACE_GETREGS, child, 0, &regs);
        ins = (long long unsigned int)ptrace(PTRACE_PEEKTEXT, child, regs.rip, 0);
        printf("cnt = %02d, rip = 0x%08llx, ins = 0x%016llx\n", cnt, regs.rip, ins);
        if (ptrace(PTRACE_SINGLESTEP, child, 0, 0) < 0) {
            printf("ptrace single step error!\n");
            return;
        }
        wait(&status);
    }
    printf("total instructions : %d\n", cnt);
    printf("you can use \"objdump -d helloworld\" to compare it !\n");
    return;
}

int main()
{
    pid_t child = fork();

    if (child == 0) {
        // child
        if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
            printf("child : trace me error!\n");
            return 0;
        }
        execl("./helloworld", "helloworld", NULL);
    } else if (child > 0) {
        // father
        get_ins_cnt(child);
    } else {
        printf("error fork!\n");
    }

    return 0;
}